package com.starsoft.smdc.crawler.sina;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.databind.JsonNode;
import com.starsoft.frame.fileimport.JsonReader;
import com.starsoft.frame.fileimport.pojo.Column;
import com.starsoft.frame.fileimport.pojo.DataTable;
import com.starsoft.frame.fileimport.pojo.NullType;
import com.starsoft.frame.fileimport.pojo.Table;
import com.starsoft.frame.fileimport.pojo.Table.TitleType;
import com.starsoft.frame.fileimport.pojo.ValueType;
import com.starsoft.frame.util.DateUtil;
import com.starsoft.frame.util.MapUtil;
import com.starsoft.smdc.bean.SmdcMarketDaily;
import com.starsoft.smdc.bean.SmdcMarketDailyId;
import com.starsoft.smdc.bean.SmdcSecurity;
import com.starsoft.smdc.crawler.common.MarketDailyCrawler;
import com.starsoft.smdc.service.MarketDailyService;
import com.starsoft.smdc.util.SecurityType;

import cn.hutool.core.collection.CollUtil;

public class MarketDailySina extends SinaService implements MarketDailyCrawler {

	private static Logger logger = LoggerFactory.getLogger(MarketDailySina.class);

	@Override
	public List<SmdcMarketDaily> update(SmdcSecurity security, Date begin) {
		return update(Arrays.asList(security), Arrays.asList(begin));
	}

	@Override
	public List<SmdcMarketDaily> update(List<SmdcSecurity> securityList, List<Date> begin) {
		Date end = new Date();
		if(holidayService.isBeforeClose(end)){
			end = holidayService.getNextBusinessDay(end, -1);
		} else {
			end = holidayService.getBusinessDay(end, true);
		}
		
		List<SmdcMarketDaily> result = new ArrayList<SmdcMarketDaily>();
		for (int i = 0; i < securityList.size(); i++) {
			SmdcSecurity security = securityList.get(i);
			try {
				if (SecurityType.isFund(security.getSecType())) {
					List<SmdcMarketDaily> navList = getFundNav(security, begin.get(i), end);
					updateOfMarket(security, navList);
					marketDailyDao.saveOrUpdateBatch(navList);
					result.addAll(navList);
				}
			} catch (Exception e) {
				logger.error("", e);
			}
		}
		return result;
	}
	
	private void updateOfMarket(SmdcSecurity security, List<SmdcMarketDaily> navList) {
		if(!"of".equalsIgnoreCase(security.getExchange()) || navList.size()<2) return;
		navList.sort((a,b)->a.getId().getTradeDate().compareTo(b.getId().getTradeDate()));
		for (int i = 1; i < navList.size(); i++) {
			SmdcMarketDaily nav = navList.get(i);
			nav.setClosePrice(nav.getSecNav());
			nav.setPercent(nav.getSecNav() / navList.get(i - 1).getSecNav() - 1);
		}
	}

	private List<SmdcMarketDaily> getFundNav(SmdcSecurity security, Date begin, Date endDate) throws ParseException {
		Map<Date, SmdcMarketDaily> marketMap = new HashMap<Date, SmdcMarketDaily>();
		begin = DateUtil.floorTime(begin);
		if (endDate.before(begin)) {
			return new ArrayList<>();
		}
		begin = holidayService.getNextBusinessDay(begin, -1);
		String apiName = "fundNav";
		String[] params = { security.getTicker(), DateUtil.toString(begin, "yyyy-MM-dd"),
				DateUtil.toString(endDate, "yyyy-MM-dd"), "1", String.valueOf(new Date().getTime()) };
		String response = this.request(apiName, params);
		JsonNode responseJsonPageOne = getJsonNode(response);
		JsonNode toltalNumNode = responseJsonPageOne.get("result").get("data").get("total_num");
		int toltalNum = toltalNumNode.asInt();
		int toltalPage = (int) Math.ceil(toltalNum/20.0);
		
		List<Column> columnList = new ArrayList<Column>();
		columnList.add(new Column("fbrq", "tradeDate", ValueType.Date, NullType.notnull, "yyyy-MM-dd HH:mmm:ss"));
		columnList.add(new Column("jjjz", "secNav", ValueType.Double, NullType.nullable));
		Table table = new Table(TitleType.OnlyCode, columnList);
		for(int i=1;i<=toltalPage;i++){
			String content = null;
			if(i==1){
				JsonNode dataNode = responseJsonPageOne.get("result").get("data").get("data");
				content = dataNode.toString();
			} else {
				params[3] = String.valueOf(i);
				response = this.request(apiName, params);
				JsonNode responseJson = getJsonNode(response);
				JsonNode dataNode = responseJson.get("result").get("data").get("data");
				content = dataNode.toString();
			}

			JsonReader reader = new JsonReader();
			DataTable dataTable = reader.read(content, table);
			
			for (Map<String, Object> mapObject : dataTable.getData()) {
				Date tradeDate = (Date)mapObject.get("tradeDate");
				tradeDate = holidayService.getBusinessDay(tradeDate, true);
				mapObject.put("tradeDate", tradeDate);
				if (tradeDate.before(begin)) {
					continue;
				}

				SmdcMarketDailyId id = new SmdcMarketDailyId(security.getSecId(), tradeDate);
				SmdcMarketDaily marketDaily = marketDailyDao.get(id);
				if (marketDaily == null) {
					if(!"of".equalsIgnoreCase(security.getExchange())) continue;
					marketDaily = new SmdcMarketDaily();
					marketDaily.setId(id);
				}
				MapUtil.updateBean(marketDaily, mapObject);
				marketMap.put(tradeDate, marketDaily);
			}
		}
		return new ArrayList(marketMap.values());
	}

}
